In recent years, various server-side scripting languages have been redesigned to improve Web development. Particularly, the use of various front-end declarative languages, which involve mixed declarative and imperative constructions, has become popular due to the many advantages existing in such use over mere imperative logic. The advantages include better isolation and detection of faults (e.g. a defective component does not break an entire rendered page), capability to write shorter, cleaner, and more verifiable code, and optimization opportunities due to the ease in rearranging strongly constrained business logic. Examples of these mixed construction, front-end declarative languages include XHP/PHP, Preparables, etc. The design of these particular front-end declarative languages contains a domain specific declarative language (DSDL) embedded inside an imperative language, where the DSDL is constructed by a higher level imperative code. As in any programming language, understanding code behavior is essential in the development and production of these front-end declarative languages.
Traditionally, web developers utilize a stack trace, or backtrace, as a tool for debugging and obtaining diagnostic information about executed computer program code. However, using the traditional stack trace for understanding code written in a mixed construction language can be difficult due to the large number of choices happening during execution of imperative and declarative logic. Ordinarily, a stack trace provides a reported sequence of nested functions, represented by stack frames, called up to the current point where the stack trace is generated. In the case of an execution failure, this means only stack frames up to the point where a failure occurred are generated, but not necessarily at the point where the cause of the failure exists. Further, sibling functions of the called functions are not recorded, and so dependency relationships are not visible in a traditional stack trace. As such, a web developer is not guaranteed to see all semantic and dependency aspects of a computer program by looking at just the stack trace at the end of execution.
In the case of mixed construction languages, it is particularly difficult for the traditional stack trace to trace the sequence of executed functions through the layers of imperative and declarative constructions. For example, a stack trace for an XHP rendering loop will only present the lowest-level declarative element that failed when the code was rendered, i.e., the stack trace of the interpreter loop of the declarative language. However, the root cause of the failure is not necessarily at the interpreter loop, but often in some other component. This is particularly problematic in production where the failure is not easily reproduced and a traditional stack trace is all that is available. One solution to address limitations of the traditional stack trace has been attempted in a stopgap system in Preparables, by use of a “Preparable Stack.” However, a Preparable Stack only traces the immediate dependencies of the current Preparable, leaving out crucial information about the origins of those dependencies (i.e., how the dependencies came about). It is desirable to identify dependency relationships in addition to semantic information describing how those relationships were created in order to diagnose the root cause of a failure.
Thus, it is desirable to have a framework that enables developers to investigate code failures and improve production efficiency of computer programs written in mixed declarative and imperative construction languages.